package cn.lijiajia3515.starter.web.autoconfigure;

import cn.lijiajia3515.starter.web.jackson.CairoJacksonProperties;
import cn.lijiajia3515.starter.web.jackson.StandardJackson2ObjectMapperBuilderCustomizer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import java.util.HashMap;
import java.util.List;

/**
 * spring web 优化配置
 */
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
@ConditionalOnClass(value = {ObjectMapper.class, MappingJackson2HttpMessageConverter.class})
public class SpringWebAutoConfiguration {

	/**
	 * 优先级最高的 转换器 由 spring jackson properties 配置
	 *
	 * @param mapper spring objectMapper
	 * @return message converter
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	MappingJackson2HttpMessageConverter highestJsonHttpMessageConverter(ObjectMapper mapper) {
		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
		converter.setSupportedMediaTypes(List.of(
			new MediaType("application", "json")
		));
		return converter;
	}

	/**
	 * 优先级最低的 转换器(spring mvc config default除外) 由 spring jackson properties 配置
	 *
	 * @param mapper spring jackson objectMapper
	 * @return message converter
	 */
	@Bean
	@Order
	MappingJackson2HttpMessageConverter lowestJsonHttpMessageConverter(ObjectMapper mapper) {
		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
		converter.setSupportedMediaTypes(List.of(
			new MediaType("application", "*+json")
		));
		return converter;
	}

	/**
	 * spring actuator 配置 固定写法 (spring admin 前端无扩展导致 ,在此优化)
	 *
	 * @return message converter
	 */
	@Bean
	@Order(100)
	public MappingJackson2HttpMessageConverter springBootActuatorHttpMessageConverter(ApplicationContext context) {
		CairoJacksonProperties properties = CairoJacksonProperties.builder()
			.dateFormat(StdDateFormat.class.getName())
			.generator(new HashMap<>() {{
				put(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
			}})
			.build();
		Jackson2ObjectMapperBuilderCustomizer customizer = new StandardJackson2ObjectMapperBuilderCustomizer(context, properties);
		Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
		customizer.customize(builder);

		ObjectMapper objectMapper = builder.createXmlMapper(false).build();

		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
		converter.setSupportedMediaTypes(List.of(
			new MediaType("application", "vnd.spring-boot.actuator.*+json")
		));

		return converter;
	}

//	@Slf4j
//	@EnableWebMvc
//	@ConditionalOnClass(value = {CairoHttpMessageConverter.class})
//	// @Order(300)
//	@Configuration(proxyBeanMethods = false)
//	public static class SpringBootWebConfig implements WebMvcConfigurer {
//		private final CairoHttpMessageConverter messageConverter;
//
//		public SpringBootWebConfig(@Qualifier("springBootActuatorHttpMessageConverter") CairoHttpMessageConverter messageConverter) {
//			this.messageConverter = messageConverter;
//		}
//
//		@Override
//		public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//			converters.add(messageConverter);
//		}
//	}


}
